﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Xml;
using System.Web.Services.Protocols;

namespace Aquasoft.Iszr.Proxy.WebServices
{
    /// <summary>
    /// Interceptor registrator.
    /// You can use <see cref="AddInterceptor"/> or <see cref="InsertInterceptor"/> to add your own interceptor(s).
    /// For example, add wrapper for your IoC manager.
    /// </summary>
    public sealed class IszrMessageInterceptor
    {
        static IszrMessageInterceptor()
        {
            Instance = new IszrMessageInterceptor();
        }
        private IszrMessageInterceptor()
        {
        }
        public static IszrMessageInterceptor Instance { get; private set; }

        private List<IIszrMessageInterceptor> interceptors = new List<IIszrMessageInterceptor>();

        public void AddInterceptor(IIszrMessageInterceptor interceptor)
        {
            interceptors.Add(interceptor);
        }
        public void InsertInterceptor(IIszrMessageInterceptor interceptor)
        {
            interceptors.Insert(0, interceptor);
        }
        public void RemoveInterceptor(IIszrMessageInterceptor interceptor)
        {
            interceptors.Remove(interceptor);
        }
        public T CallInterceptors<T>(Func<IIszrMessageInterceptor, T> caller, IIszrMessageInterceptor lastInterceptor) where T : class
        {
            foreach (var item in interceptors)
            {
                var result = caller(item);
                if (result != null)
                    return result;
            }
            return caller(lastInterceptor);
        }
        public WebResponse OnGetWebResponse(IszrServiceBase service, WebRequest request)
        {
            return CallInterceptors(i => i.GetWebResponse(service, request), service);
        }

        public WebResponse OnGetWebResponseAsync(IszrServiceBase service, WebRequest request, IAsyncResult result)
        {
            return CallInterceptors(i => i.GetWebResponseAsync(service, request, result), service);
        }

        public WebRequest OnGetWebRequest(IszrServiceBase service, Uri uri)
        {
            return CallInterceptors(i => i.GetWebRequest(service, uri), service);
        }

        public XmlReader OnGetReaderForMessage(IszrServiceBase service, SoapClientMessage message, int bufferSize)
        {
            return CallInterceptors(i => i.GetReaderForMessage(service, message, bufferSize), service);
        }

        public XmlWriter OnGetWriterForMessage(IszrServiceBase service, SoapClientMessage message, int bufferSize)
        {
            return CallInterceptors(i => i.GetWriterForMessage(service, message, bufferSize), service);
        }
    }

    /// <summary>
    /// Interceptor interface. 
    /// Each method can return null to inform, that this method is not intercepted.
    /// </summary>
    public interface IIszrMessageInterceptor
    {
        WebResponse GetWebResponse(IszrServiceBase service, WebRequest request);

        WebResponse GetWebResponseAsync(IszrServiceBase service, WebRequest request, IAsyncResult result);

        WebRequest GetWebRequest(IszrServiceBase service, Uri uri);

        XmlReader GetReaderForMessage(IszrServiceBase service, SoapClientMessage message, int bufferSize);

        XmlWriter GetWriterForMessage(IszrServiceBase service, SoapClientMessage message, int bufferSize);
    }
}
